import os
from PyQt5.QtCore import Qt, pyqtSlot
from PyQt5 import QtWidgets
from PyQt5.Qt import QMainWindow, QFont, QToolBar, QIcon, QPixmap, QSize, \
    QColor, QMenu, QCursor
from PyQt5.QtWidgets import QAction

from common.objects.det_object import DetObject
from common.settings import Settings
from .BaseWindow import BaseWindow
from ..widgets.LabelPro import LabelPro
from ..widgets.ImgViewer import ImgViewer
from ..ui_utils import kill_proc_tree, explorer
from .._config import UI_RES_PATH, CAM_STYLE
from common.utils.NovishLogger import logger

__doc__ = 'UI 主界面'
resz = r'resource/static/resz.png'
resc = r'resource/static/resc.png'
resz_c = r'resource/static/ruiqi.png'

# imgz = r'resource/static/gjz.png'
# imc = r'resource/static/gjc.png'
# imgz_c = r'resource/static/gjz_c.png'


class UiMain(QMainWindow, BaseWindow):
    def __init__(self, cam_matrix):
        super(UiMain, self).__init__()

        self.cam_matrix = cam_matrix
        # 左侧图片显示的最大数量
        self.ui_dock_photos = 1000
        self.resize(1980, 1080)
        self.textEdit_send_sbar = QtWidgets.QScrollBar()

        # 2.给这个滚动条添加属性
        self.textEdit_send_sbar.setStyleSheet("""
                     QScrollBar:vertical {
                          border-width: 0px;
                          border: none;
                          background:rgba(64, 65, 79, 0);
                          width:12px;
                          margin: 0px 0px 0px 0px;
                      }
                      QScrollBar::handle:vertical {
                          background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
                          stop: 0 #aaaaff, stop: 0.5 #aaaaff, stop:1 #aaaaff);
                          min-height: 20px;
                          max-height: 20px;
                          margin: 0 0px 0 0px;
                          border-radius: 6px;
                      }
                      QScrollBar::add-line:vertical {
                          background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
                          stop: 0 rgba(64, 65, 79, 0), stop: 0.5 rgba(64, 65, 79, 0),  stop:1 rgba(64, 65, 79, 0));
                          height: 0px;
                          border: none;
                          subcontrol-position: bottom;
                          subcontrol-origin: margin;
                      }
                      QScrollBar::sub-line:vertical {
                          background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
                          stop: 0  rgba(64, 65, 79, 0), stop: 0.5 rgba(64, 65, 79, 0),  stop:1 rgba(64, 65, 79, 0));
                          height: 0 px;
                          border: none;
                          subcontrol-position: top;
                          subcontrol-origin: margin;
                      }
                      QScrollBar::sub-page:vertical {
                      background: rgba(64, 65, 79, 0);
                      }

                      QScrollBar::add-page:vertical {
                      background: rgba(64, 65, 79, 0);
                      }
                      """)

    def closeEvent(self, event):
        reply = QtWidgets.QMessageBox.information(self, '提示', '是否关闭窗口？\nDo you want to close the window?',
                                                  QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
        if reply == QtWidgets.QMessageBox.Yes:
            kill_proc_tree(os.getpid(), True)
        else:
            event.ignore()

    def _connect(self):
        pass

    def _initUI(self):
        """ 控件/布局 """
        self.setWindowIcon(QIcon(str(UI_RES_PATH / 'logo.png')))

        self.central = QtWidgets.QWidget(self)
        self.grid_main = QtWidgets.QGridLayout(self.central)

        self.toolbar = QToolBar(self)
        self.toolbar.setMovable(False)
        self.toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.toolbar.setStyleSheet("background-color: rgb(0,175,219);color: black;")
        self.addToolBar(Qt.TopToolBarArea, self.toolbar)

        self.toolbar_btn_custom()

        self.group_custom()

        self.cam_custom()

        self.local_custom()

        self.info_custom()

        self.btn_custom()

        self.dock_custom()

        self.stretch_custom()

        self.setCentralWidget(self.central)

    def stretch_custom(self):
        self.grid_main.setRowStretch(0, 6)
        self.grid_main.setRowStretch(1, 1)
        self.grid_main.setColumnStretch(0, 3)
        self.grid_main.setColumnStretch(1, 1)

    def group_custom(self):
        for item in [
            ('cam', '相机', (0, 0)),
            ('local', '位置信息', (1, 0)),
            ('info', '信息', (0, 1)),
            ('btn', '功能', (1, 1))
        ]:
            self.QGroupBoxPack(*item)

    def toolbar_btn_custom(self):
        for item in [
            ('data', '数据展示'),
            ('control', ' '),
            ('standard', ''),
            ('det_details', '检测详情'),
            ('run_details', '运行详情'),
            ('cam', '-'),
            # ('log', '日志'),
            ('help', ' '),
        ]:
            self.QActionPack(*item, self.toolbar, str(UI_RES_PATH / ('%s.png' % item[0])))
        self.action_standard.setVisible(False)
        self.action_det_details.setVisible(False)
        self.action_run_details.setVisible(False)

    def cam_custom(self):
        self.cam_list = []
        self.cam_position = [(row, column) for row in range(self.cam_matrix[0]) for column in
                             range(self.cam_matrix[1])]  # 相机画面矩阵
        for i, p in enumerate(self.cam_position):
            cam_name = 'cam%d' % i  # 按行索引
            self.cam_list.append(cam_name)
            setattr(self, cam_name, LabelPro())
            self.QCamBand(self.groupbox_cam, cam_name, cam_name, p)

    def local_custom(self):
        q_image = QPixmap(resz_c)
        setattr(self, 'local_pic', QtWidgets.QLabel(self))
        self.__dict__['local_pic'].setAlignment(Qt.AlignCenter)
        self.__dict__['local_pic'].setPixmap(q_image)
        self.grid_local: QtWidgets.QGridLayout
        self.grid_local.addWidget(self.__dict__['local_pic'])

    def info_custom(self):
        for item in [
            ('FINAL_FLAG', '综合判定Final Result', '--'),
            ('line',) * 3,
            ('DET_TIME', '检测时间Detection Time', '0ms'),
        ]:
            self.QInfoBand(*item, self.groupbox_info)

        font = QFont()
        font.setBold(True)
        font.setPointSize(25)
        self.label_final_flag.setFont(font)
        self.FINAL_FLAG.setFont(font)
        self.FINAL_FLAG.setStyleSheet('color: rgb(128, 128, 128)')
        # self.grid_info.setContentsMargins(-1, -1, -1, 800)

    def btn_custom(self):
        for item in [
            ('CONTROL', '开始运行', (1, 0)),
            ('SET', '设置', (2, 0)),
        ]:
            self.QBtnPack(*item)

    def dock_custom(self):
        for item in [
            ('det_details', '检测详情', 300, None, Qt.LeftDockWidgetArea),
            ('run_details', '运行详情', 150, None, Qt.RightDockWidgetArea),
            ('data', '运行信息', None, 260, Qt.BottomDockWidgetArea),
        ]:
            self.QDockBand(*item)

    def _dockContent(self, var, content_obj, grid_obj):
        self.QDockContent(var, content_obj, grid_obj)
        if var == 'det_details':
            """ 检测详情[左侧Dock] """
            scroll_obj, scroll_content_obj, grid_scroll_obj = self.QScrollAreaPack(var, content_obj)
            grid_obj.addWidget(scroll_obj, 0, 0)

            splitter_obj = self.QSplitterPack('switch', scroll_content_obj)
            for var, txt in [
                ('SHOW_ALL', '全部'),
                ('SHOW_OK', '合格'),
                ('SHOW_NG', '不合格')
            ]:
                setattr(self, var, QtWidgets.QRadioButton(txt, splitter_obj))
                splitter_obj.addWidget(getattr(self, var))
            self.SHOW_ALL.setChecked(True)
            grid_scroll_obj.addWidget(splitter_obj)
            self.action_det_details.setVisible(True)
            self.action_det_details.triggered.connect(
                lambda: self.dock_det_details.setVisible(not (self.dock_det_details.isVisible())))

        elif var == 'run_details_all':
            """ 运行详情[右侧Dock] """
            self.dock_menu = QMenu(self)

            for item in [
                ('RUN_TOTAL', '总数 Total', '0'),
                ('RUN_OK_NUM', '合格数 OK', '0'),
                ('RUN_NG_NUM', '不合格数 NG', '0'),
            ]:
                splitter_item_obj = self.QInfoItem(*item, content_obj, alignment=Qt.AlignCenter | Qt.AlignRight)
                grid_obj.addWidget(splitter_item_obj)
            font = QFont()
            font.setPointSize(10)
            self.RUN_TOTAL.setFont(font)
            self.label_run_total.setFont(font)
            self.RUN_OK_NUM.setFont(font)
            self.label_run_ok_num.setFont(font)
            self.RUN_NG_NUM.setFont(font)
            self.label_run_ng_num.setFont(font)

            list_name = var.upper()
            setattr(self, list_name, QtWidgets.QListWidget(content_obj))
            list_obj: QtWidgets.QListWidget = getattr(self, list_name)
            list_obj.setContextMenuPolicy(Qt.CustomContextMenu)
            list_obj.customContextMenuRequested.connect(self.show_dock_menu)
            grid_obj.addWidget(list_obj)
            self.action_run_details.setVisible(True)
            self.action_run_details.triggered.connect(
                lambda: self.dock_run_details.setVisible(not (self.dock_run_details.isVisible())))

        elif var == 'json_details':
            """ 运行信息[底部Dock] """
            self.dock_json_details.setFeatures(
                QtWidgets.QDockWidget.DockWidgetFloatable | QtWidgets.QDockWidget.DockWidgetMovable)

            list_name = var.upper()
            setattr(self, list_name, QtWidgets.QListWidget(content_obj))
            list_obj: QtWidgets.QListWidget = getattr(self, list_name)
            grid_obj.addWidget(list_obj, 0, 0)

    def _detDockImgs(self, img_count):
        def __Qdetimg(i, parent, grid, p):
            img_name = 'det_img%d' % i
            setattr(self, img_name, ImgViewer(parent))
            img_obj: QtWidgets.QLabel = getattr(self, img_name)
            img_obj.setText('加载中')
            img_obj.setStyleSheet('border-width: 2px;border-style: solid;border-color: rgb(225, 225, 225);')
            img_obj.setFixedSize(215, 100)
            img_obj.setAlignment(Qt.AlignCenter)
            grid.addWidget(img_obj, *p)

        current_img_count = self.grid_scroll_det_details.count()
        new_cnt = img_count - current_img_count
        if new_cnt > 0:
            for i in range(current_img_count, img_count + 1):
                __Qdetimg(i, self.scroll_content_det_details, self.grid_scroll_det_details, (i, 0))
        elif new_cnt < 0:
            for i in range(img_count + 1, current_img_count):
                img_name = 'det_img%d' % i
                img_obj = getattr(self, img_name)
                img_obj.deleteLater()
                del img_obj

    def det_img_filter(self, img, img_path, index, flag, img_struct):
        """ 筛选在检测详情中显示的图片 """
        attribute_name = f'det_img{index:d}'
        label = self.__dict__[attribute_name]
        # logger.debug(f"attribute_name:{attribute_name}")
        # if self.SHOW_ALL.isChecked():
        #     label.setVisible(True)
        # elif self.SHOW_OK.isChecked():
        #     label.setVisible(False) if flag else label.setVisible(True)
        # elif self.SHOW_NG.isChecked():
        #     label.setVisible(True) if flag else label.setVisible(False)
        label.setStyleSheet(
            CAM_STYLE.format(255, 0, 0) if flag else CAM_STYLE.format(0, 255, 0)
        )
        label.setScaledContents(True)
        label.setPixmap(img)
        label.img_path = img_path
        label.img_struct = img_struct

        self.scroll_det_details.verticalScrollBar().setValue(100 * index - 600)

    def QCamBand(self, parent, cam_name, title, p):
        """ 相机组件 """

        def _btn(var, txt, icon='', tip=''):
            btn_name = 'BTN_' + var.upper()
            setattr(self, btn_name, QtWidgets.QPushButton(self))
            btn_obj: QtWidgets.QPushButton = getattr(self, btn_name)
            btn_obj.setFlat(True)
            btn_obj.setText(txt)
            btn_obj.setFixedHeight(30)
            btn_obj.setIconSize(QSize(30, 30))
            btn_obj.setToolTip(tip) if tip else None
            btn_obj.setIcon(QIcon(icon)) if icon else None
            return btn_obj

        splitter_cam_obj = self.QSplitterPack(cam_name, parent, Qt.Vertical)
        splitter_title_obj = self.QSplitterPack('title_%s' % cam_name, parent)
        # title
        title_btn_obj = _btn(cam_name, title, str(UI_RES_PATH / 'max.png'), '点击放大/还原此相机画面')
        font = QFont()
        font.setBold(True)
        title_btn_obj.setFont(font)
        title_btn_obj.clicked.connect(lambda: self.__cam_full(cam_name.lower()))
        splitter_title_obj.addWidget(title_btn_obj)
        # img
        font = QFont()
        font.setPointSize(20)
        cam_name_obj: LabelPro = getattr(self, cam_name)
        cam_name_obj.setText('加载中LOADING...')
        cam_name_obj.setFont(font)
        cam_name_obj.setAlignment(Qt.AlignCenter)
        cam_name_obj.setStyleSheet(
            'border-width:2px;border-radius:10px;border-style:solid;border-color: rgb(205, 205, 205);')

        splitter_cam_obj.addWidget(splitter_title_obj)
        splitter_cam_obj.addWidget(cam_name_obj)

        self.grid_cam.addWidget(splitter_cam_obj, *p)

    def QGroupBoxPack(self, var, title, p):
        groupbox_name = f'groupbox_' + var
        setattr(self, groupbox_name, QtWidgets.QGroupBox(self))
        groupbox_obj: QtWidgets.QGroupBox = getattr(self, groupbox_name)
        groupbox_obj.setTitle(title)
        grid_name = 'grid_' + var
        setattr(self, grid_name, QtWidgets.QGridLayout(groupbox_obj))
        self.grid_main.addWidget(groupbox_obj, *p)

    def QInfoBand(self, info_name, txt, value, parent):
        """ 信息组件 """
        self.grid_info: QtWidgets.QGridLayout
        if info_name == 'line':
            self.grid_info.addWidget(self.QDivider(parent))
        else:
            font = QFont()
            font.setPointSize(14)
            splitter_info_obj = self.QInfoItem(info_name, txt, value, parent, alignment=Qt.AlignCenter | Qt.AlignRight,
                                               font=font)
            self.grid_info.addWidget(splitter_info_obj)

    def QBtnPack(self, var, txt, p):
        font = QFont()
        font.setPointSize(16)
        btn_name = 'BTN_' + var.upper()
        setattr(self, btn_name, QtWidgets.QPushButton(self.groupbox_btn))
        self.__dict__[btn_name].setText(txt)
        self.__dict__[btn_name].setFixedHeight(60)
        self.__dict__[btn_name].setFont(font)
        self.grid_btn.addWidget(self.__dict__[btn_name], *p)

    @pyqtSlot()
    def show_dock_menu_all_items(self):
        """ 弹出菜单 """
        self.RUN_DETAILS_ALL: QtWidgets.QListWidget
        self.dock_menu.clear()
        current_item = self.RUN_DETAILS_ALL.currentItem()
        item_data = current_item.data(Qt.UserRole)

        if current_item and item_data:
            # logger.debug(f"what_this:{what_this}")
            data = item_data
            # logger.debug(f"data:{data}")
            if isinstance(data, dict):
                items = data['path'] if 'path' in data else {}
                for k, v in items.items():
                    # logger.debug(f"k:{k},v:{v}")
                    self.dock_menu.addAction(f'查看{k}图片', lambda a=v: explorer(a))
            self.dock_menu.move(QCursor.pos())
            self.dock_menu.show()

    @pyqtSlot()
    def show_dock_menu_current_item(self):
        """ 当前工具列表的右键弹出菜单 """
        self.RUN_DETAILS_CURRENT: QtWidgets.QListWidget
        self.dock_menu.clear()
        det_obj = None
        current_item = self.RUN_DETAILS_CURRENT.currentItem()
        if current_item and current_item.data(Qt.UserRole):
            det_obj = current_item.data(Qt.UserRole)
        if isinstance(det_obj, DetObject):
            self.dock_menu.addAction(f'查看检测图片', lambda a=det_obj.det_img_path: explorer(a))
            self.dock_menu.addAction(f'查看原始图片', lambda a=det_obj.ori_img_path: explorer(a))
        self.dock_menu.move(QCursor.pos())
        self.dock_menu.show()

    @pyqtSlot(str)
    def __cam_full(self, cam):
        """ 点击相机画面Title放大/还原相机画面 """
        if len(self.cam_list) == 1: return
        cam_list = self.cam_list.copy()
        cam_list.remove(cam)
        for name in cam_list:
            name = 'splitter_' + name
            flag = self.__dict__[name].isVisible()
            self.__dict__[name].setVisible(not flag)
        if flag:
            self.grid_cam.addWidget(self.__dict__[f'splitter_{cam}'], 0, 0, -1, -1)
        else:
            for i, p in enumerate(self.cam_position):
                i, p = p if isinstance(p[-1], (list, tuple)) else (i, p)
                self.grid_cam.addWidget(self.__dict__[f'splitter_cam{i}'], *p)

    # 界面上需要动态修改的参数
    @property
    def ui_dock_photos(self):
        # 检测详情照片数量
        return getattr(self, '_photos', None)

    @ui_dock_photos.setter
    def ui_dock_photos(self, v: int):
        self._detDockImgs(v)
        if 'img_count_per_piece' in self.__dict__:
            self.img_count_per_piece.value = v
        self._photos = v

    @property
    def ui_final_flag(self):
        # 综合判定 亦是间隙到来的标志
        return self.GetValue(self.FINAL_FLAG)

    @ui_final_flag.setter
    def ui_final_flag(self, v: str):
        v = v.upper()
        _map = {'OK': 'green', 'NG': 'red'}
        self.SetColorText(self.FINAL_FLAG, v, _map.get(v, 'black'))
        # 间隙
        self._run()

    @property
    def ui_ok_cnt(self):
        # 合格数
        return self.GetValue(self.OK_CNT)

    @ui_ok_cnt.setter
    def ui_ok_cnt(self, v: str):
        self.SetColorText(self.OK_CNT, v, 'green')

    @property
    def ui_ng_cnt(self):
        # 不合格数
        return self.GetValue(self.OK_CNT)

    @ui_ng_cnt.setter
    def ui_ng_cnt(self, v: str):
        self.SetColorText(self.NG_CNT, v, 'red')

    @property
    def ui_det_time(self):
        # 检测时间
        return self.GetValue(self.DET_TIME)

    @ui_det_time.setter
    def ui_det_time(self, v: str):
        self.SetValue(self.DET_TIME, v)
        # if 'end'in v:
        #     reply = QtWidgets.QMessageBox.information(self, '提示', '是否继续？', QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
        #     if reply == QtWidgets.QMessageBox.Yes:
        #         self.run_flag2 = True
        #     else:
        #         self.run_flag2 = False

    @property
    def ui_run_time(self):
        # 运行时间
        return self.GetValue(self.RUN_TIME)

    @ui_run_time.setter
    def ui_run_time(self, v: float):
        v = '%.2fms' % v
        self.SetValue(self.RUN_TIME, v)

    @property
    def ui_data_item(self):
        # 运行详情条目
        return self.RUN_DETAILS_ALL.count()

    @ui_data_item.setter
    def ui_data_item(self, v: [str, dict]):
        """
        全部工件的列表。
        """
        self.RUN_DETAILS_ALL: QtWidgets.QListWidget
        if isinstance(v, dict):
            data = v
            v = v.get('flag', 'unknown')
            # data = {'num': 0, 'model0': None, 'path0': None}
            self.RUN_DETAILS_ALL.insertItem(0, str(v))
            uri_dict = {'_det_img_path': data['_det_img_path'], '_ori_img_path': data['_ori_img_path']}
            self.RUN_DETAILS_ALL.item(0).setWhatsThis('%s' % uri_dict)
            tip = '\n\n'.join(['[%s] \n%s' % (m, n) for m, n in data['model'].items()]) if 'model' in data else ''
            self.RUN_DETAILS_ALL.item(0).setToolTip(tip)
            q_image = QPixmap(resz_c)
            self.__dict__['local_pic'].setPixmap(QPixmap(q_image))
        else:
            logger.warning('数据类型错误')
        self.RUN_TOTAL.setText(str(int(self.RUN_TOTAL.text()) + 1))
        if any([k in v for k in ['不合格', 'ng', 'NG']]):
            self.RUN_NG_NUM.setText(str(int(self.RUN_NG_NUM.text()) + 1))
            self.RUN_NG_NUM.setStyleSheet('color: red')
            self.RUN_DETAILS_ALL.item(0).setBackground(QColor('red'))
        elif any([k in v for k in ['合格', 'ok', 'OK']]):
            self.RUN_OK_NUM.setText(str(int(self.RUN_OK_NUM.text()) + 1))
            self.RUN_OK_NUM.setStyleSheet('color: green')
            self.RUN_DETAILS_ALL.item(0).setBackground(QColor('green'))
        if self.RUN_DETAILS_ALL.count() == 300:
            self.RUN_DETAILS_ALL.takeItem(self.RUN_DETAILS_ALL.count() - 1)
        self._run()

    @property
    def ui_current_item_result(self):
        # 运行详情条目
        return self.RUN_DETAILS_CURRENT.count()

    @ui_current_item_result.setter
    def ui_current_item_result(self, sum_result_list_item: [str, dict]):
        self.RUN_DETAILS_CURRENT: QtWidgets.QListWidget
        # 新的工件来的时候，先进行清空
        self.RUN_DETAILS_CURRENT.clear()
        for idx, sum_result_item in enumerate(sum_result_list_item):
            # sum_result_item是格式如下的字典:
            # {'class_name': 'dirty', 'path': {'检测': 'result\\0\\det\\08\\15\\NG\\20240815100503880635-pc2-flg1.jpg',
            # '原图': 'result\\0\\ori\\08\\15\\NG\\20240815100503880635-pc2-flg1.jpg'}, 'flag_ok': False}
            v = sum_result_item
            if isinstance(v, dict):
                logger.debug(f"v:{v}")
                flag_ok = v.get('flag_ok', True)
                class_name = v.get("class_name", 'unknown')
                chinese_defect_name = Settings.DEFECT_MAP[class_name]
                text_label = f"{idx + 1}-{chinese_defect_name}"
                uri_dict = {'_det_img_path': v['_det_img_path'], '_ori_img_path': v['_ori_img_path']}
                self.RUN_DETAILS_ALL.item(0).setWhatsThis('%s' % uri_dict)
                self.RUN_DETAILS_CURRENT.addItem(text_label)
                self.RUN_DETAILS_CURRENT.item(idx).setWhatsThis('%s' % uri_dict)  # ??
                # tip = '\n\n'.join(['[%s] \n%s' % (m, n) for m, n in data['model'].items()]) if 'model' in data else ''
                # self.RUN_DETAILS_CURRENT.item(0).setToolTip(tip)
                # q_image = QPixmap(resz_c)
                # self.__dict__['img_path'].setPixmap(QPixmap(q_image))
                # self.RUN_TOTAL.setText(str(int(self.RUN_TOTAL.text()) + 1))
                if not flag_ok:
                    # self.RUN_NG_NUM.setText(str(int(self.RUN_NG_NUM.text()) + 1))
                    # self.RUN_NG_NUM.setStyleSheet('color: red')
                    self.RUN_DETAILS_CURRENT.item(idx).setBackground(QColor('red'))
                else:
                    # self.RUN_OK_NUM.setText(str(int(self.RUN_OK_NUM.text()) + 1))
                    # self.RUN_OK_NUM.setStyleSheet('color: green')
                    self.RUN_DETAILS_CURRENT.item(idx).setBackground(QColor('green'))
                if self.RUN_DETAILS_CURRENT.count() == 300:
                    self.RUN_DETAILS_CURRENT.takeItem(self.RUN_DETAILS_CURRENT.count() - 1)
                self._run()
            else:
                logger.warning("数据类型错误")

    @property
    def ui_json_item(self):
        return self.JSON_DETAILS.count()

    @ui_json_item.setter
    def ui_json_item(self, v: str):
        self.JSON_DETAILS.insertItem(0, str(v))
        if self.JSON_DETAILS.count() == 300:
            self.JSON_DETAILS.takeItem(self.JSON_DETAILS.count() - 1)

    @property
    def ui_det_result(self):
        # 检测结果
        return self.GetValue(self.DET_RESULT)

    @ui_det_result.setter
    def ui_det_result(self, v: str):
        self.DET_RESULT.setText(v)

    @property
    def ui_cam_title(self):
        # 相机标题
        num = self.cam_matrix[0] * self.cam_matrix[1]
        return [self.__dict__['BTN_CAM%d' % i].value() for i in num]

    @ui_cam_title.setter
    def ui_cam_title(self, v: list):
        for i, name in enumerate(v):
            # 如果有f'BTN_CAM{i:d}'这个属性，则设置其文本为name
            if f'BTN_CAM{i:d}' in self.__dict__:
                self.__dict__[f'BTN_CAM{i:d}'].setText(name)
            if f'label_info_cam{i:d}' in self.__dict__:
                self.__dict__[f'label_info_cam{i:d}'].setText(name)

    @property
    def ui_run_status(self):
        # 运行状态
        return None

    @ui_run_status.setter
    def ui_run_status(self, v: list):
        def _btn(var, txt, icon=str(UI_RES_PATH / 'status_gray.png'), tip='未运行'):
            btn_name = '%s_RUN_STATUS' % var.upper()
            setattr(self, btn_name, QtWidgets.QPushButton(self))
            btn_obj: QtWidgets.QPushButton = getattr(self, btn_name)
            btn_obj.setFlat(True)
            btn_obj.setText(txt)
            btn_obj.setFixedHeight(30)
            btn_obj.setIconSize(QSize(25, 25))
            btn_obj.setToolTip(tip) if tip else None
            btn_obj.setIcon(QIcon(icon)) if icon else None
            return btn_obj

        for i, items in enumerate(v):
            splitter_title_obj = getattr(self, 'splitter_title_cam%d' % i)
            self.__dict__['BTN_CAM%d' % i].setStyleSheet('text-align: left;')
            for item in items:
                splitter_title_obj.addWidget(_btn(*item))

    @property
    def ui_cam_status(self):
        # 相机状态
        return None

    @ui_cam_status.setter
    def ui_cam_status(self, v: str):
        self.CAM_STATUS.setText(str(v))

    @property
    def ui_light_status(self):
        # 灯光状态
        return None

    @ui_light_status.setter
    def ui_light_status(self, v: str):
        self.LIGHT_STATUS.setText(str(v))

    @property
    def ui_signal_status(self):
        # 信号状态
        return None

    @ui_signal_status.setter
    def ui_signal_status(self, v: str):
        self.SIGNAL_STATUS.setText(str(v))

    def _run(self):
        pass

    def QDockContent(self, var, content_obj, grid_obj):
        pass
